/**
 * 
 */
package Dungeon;


import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import squarePackage.PlainSquare;
import squarePackage.SquareImp;
import squarePackage.TeleportPlainSquare;
import static org.junit.Assert.*;

import Enumerations.Directions;
import Enumerations.Temperature;
import Exceptions.IllegalDimensionException;
import Obstacle.Door;
import Obstacle.Wall;

/**
 * @author Pieter
 *
 */
public class LevelsTest {

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	Level<SquareImp> levels;
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		Level<SquareImp> levels = new Level(10,20,30,5);
	}

	/**
	 * @throws java.lang.Exception
	 */
	@After
	public void tearDown() throws Exception {
	}
	
	@Test 
	public final void testConstructorLevelsLegal() throws Exception{
		Level<SquareImp> newLevel = new Level<SquareImp>(15,20,25,5);
		assertEquals(newLevel.getFixedZ(), 5);
		//System.out.println(Levels.
	}

	@Test (expected =IllegalDimensionException.class)
	public final void testConstructorLevelsIlleLegal() throws Exception{
		Level<SquareImp> newLevel = new Level<SquareImp>(-15,20,25,5);
	}
	
	@Test (expected =IllegalDimensionException.class)
	public final void testConstructorLevelsIlleLegalZfixed() throws Exception{
		Level<SquareImp> newLevel = new Level<SquareImp>(15,20,25,-5);
	}
	
	@Test 
	public final void testValidCoordinates() throws IllegalDimensionException{
		Level<SquareImp> newLevel = new Level<SquareImp>(15,20,25,5);
		assertTrue(newLevel.isValidCoordinate(15, 20, 5));
		assertFalse(newLevel.isValidCoordinate(15, 20, 25));
	}
	
	@Test
	public final void levelIterator() throws IllegalDimensionException{
	
		Level<SquareImp> Level = new Level<SquareImp>(100,100,100,0);
		PlainSquare s110 = new PlainSquare();
		PlainSquare s120 = new PlainSquare();
		s120.setBorder(Directions.South, new Wall());
		PlainSquare s130= new PlainSquare();
		s130.setBorder(Directions.South, new Wall());
		s130.setBorder(Directions.East, new Wall());
		PlainSquare s150= new PlainSquare();
		s150.setBorder(Directions.North, new Wall());
		s150.setBorder(Directions.East, new Wall());

		PlainSquare s220= new PlainSquare();
		s220.setBorder(Directions.North, new Wall());
		s220.setBorder(Directions.East, new Wall(new Door()));
		s220.getBorderByDirection(Directions.East).getDoor().openDoor();
		assertTrue(s220.getBorderByDirection(Directions.East).hasDoor());
		PlainSquare s230= new PlainSquare();
		PlainSquare s240= new PlainSquare();
		PlainSquare s250= new PlainSquare();
		s250.setBorder(Directions.East, new Wall());
		PlainSquare s330= new PlainSquare();
		PlainSquare s340= new PlainSquare();
		s340.setBorder(Directions.East, new Wall());
		s340.setBorder(Directions.South, new Wall());
		PlainSquare s430= new PlainSquare();
		s430.setBorder(Directions.North, new Wall());
		s430.setBorder(Directions.East, new Wall());
		s430.setBorder(Directions.South, new Wall(new Door()));
		s430.getBorderByDirection(Directions.South).getDoor().openDoor();
		PlainSquare s440= new PlainSquare();
		s440.setBorder(Directions.East, new Wall());
		PlainSquare s450= new PlainSquare();
		s450.setBorder(Directions.East, new Wall());
		PlainSquare s350= new PlainSquare();
		PlainSquare s610= new PlainSquare();
		PlainSquare s880 = new PlainSquare();
		s610.setBorder(Directions.West, new Wall());
		s610.setBorder(Directions.East, new Wall());
		s610.setBorder(Directions.South, new Wall(new Door()));
		s610.getBorderByDirection(Directions.South).getDoor().openDoor();
		PlainSquare s620= new PlainSquare();
		s620.setBorder(Directions.West, new Wall());
		s110.setTemperature(10, Temperature.CELCIUS);
		s110.setHumidity(new BigDecimal("0.3"));
		s120.setHumidity(new BigDecimal("0.2"));
		s120.setTemperature(10, Temperature.CELCIUS);
		s130.setTemperature(10, Temperature.CELCIUS);
		s130.setMaterial(false);
		s150.setMaterial(false);
		s220.setMaterial(false);
		s230.setMaterial(false);
		s240.setMaterial(false);
		s250.setMaterial(false);
		s330.setMaterial(false);
		s340.setMaterial(false);
		s430.setMaterial(false);
		s440.setMaterial(false);
		s450.setMaterial(false);
		s350.setMaterial(false);
		s610.setTemperature(10, Temperature.CELCIUS);
		s620.setTemperature(20, Temperature.CELCIUS);
		s880.setTemperature(30, Temperature.CELCIUS);
		s880.setMaterial(false);
		s110.setMaterial(false);
		s120.setMaterial(false);
		try {
			Level.addSquareToDungeon(1, 1, 0, s110);
			Level.addSquareToDungeon(1, 2, 0, s120);
			Level.addSquareToDungeon(1, 3, 0, s130);
			Level.addSquareToDungeon(1, 5, 0, s150);
			Level.addSquareToDungeon(2, 2, 0, s220);
			Level.addSquareToDungeon(2, 3, 0, s230);
			Level.addSquareToDungeon(2, 4, 0, s240);
			Level.addSquareToDungeon(2, 5, 0, s250);
			Level.addSquareToDungeon(3, 3, 0, s330);
			Level.addSquareToDungeon(3, 4, 0, s340);
			Level.addSquareToDungeon(4, 3, 0, s430);
			Level.addSquareToDungeon(4, 4, 0, s440);
			Level.addSquareToDungeon(4, 5, 0, s450);
			Level.addSquareToDungeon(3, 5, 0, s350);
			Level.addSquareToDungeon(6, 1, 0, s610);
			Level.addSquareToDungeon(6, 2, 0, s620);
			Level.addSquareToDungeon(8, 8, 0, s880);
		} catch (Exception e) {
			
		}
		System.out.println("ZONDER ITERATOR");
		for(Object square : Level.getAllSquaresInDungeon()){
		System.out.println(square);
		}
		
		System.out.println("MET ITERATOR");
		Iterator<SquareImp> it = Level.iterator();
		while(it.hasNext()){
		System.out.println(it.next());
		}
	}
	@Test
	public final void addSquareTest() throws IllegalDimensionException{
		Level<SquareImp> level = new Level<SquareImp>(100, 100, 100, 0);
		PlainSquare plain = new PlainSquare();
		plain.setMaterial(false);
		assertTrue(level.canHaveAsSquare( plain));
		assertTrue(level.canHaveAsCoordinate(5, 5, 0));
		for(int i = 0 ; i <6 ; i++){
			assertFalse(level.hasNeighbourAt(Directions.getDirectionByOrdinal(i), 5, 5, 0));
		}
		
		
	}
	
	@Test
	public final void constructorTest() throws IllegalDimensionException{
		PlainSquare square = new PlainSquare();
		square.setMaterial(false);
		Level<SquareImp> newLevel = new Level<SquareImp>(100, 100, 100, 0);
		assertTrue(newLevel.canHaveAsCoordinate(10, 10, 0));
		assertTrue(newLevel.canHaveAsSquare(square));
		assertTrue(newLevel.canHaveAsSquareAtCoordinate(10, 10, 0, square));
	}
	

	@Test
	public final void validDimensionTest() throws IllegalDimensionException{
		Level<SquareImp> level = new Level<SquareImp>(100, 100, 100, 0);
		assertTrue(level.isValidDimension(10, 100));
	}
	
	
	@Test
	public final void slipperyTest() throws IllegalDimensionException{
		Level<SquareImp> level = new Level<SquareImp>(100, 100, 100, 0);
		assertEquals(new BigDecimal("0.00"), level.getAmountOfSlipperySquares());
	}
	
	@Test
	public final void coordinatessquaresindugneontest() throws IllegalDimensionException{
		Level<SquareImp> level = new Level<SquareImp>(100, 100, 100, 0);
		System.out.println(level.getCoordinatesAndSquaresInDungeon());
	}
	
	
	@Test
	public final void preferencewalltesting() throws IllegalDimensionException{
		Level<SquareImp> newLevel = new Level<SquareImp>(100, 100, 100, 0);
		
		PlainSquare square = new PlainSquare();
		PlainSquare neigboor = new PlainSquare();
		
		square.setBorder(Directions.North, new Wall());
		neigboor.setBorder(Directions.South, new Wall(new Door()));
		
		assertEquals(square.getBorderByDirection(Directions.North),newLevel.preferencedWall(square, neigboor, Directions.North, Directions.South));
		
		
	}
	
	@Test
	public final void preferencewalltesting2() throws IllegalDimensionException{
		Level<SquareImp> newLevel = new Level<SquareImp>(100, 100, 100, 0);
		
		PlainSquare square = new PlainSquare();
		PlainSquare neigboor = new PlainSquare();
		
		square.setBorder(Directions.North, new Wall());
		neigboor.setBorder(Directions.South, null);
		
		assertEquals(square.getBorderByDirection(Directions.North),newLevel.preferencedWall(square, neigboor, Directions.North, Directions.South));
		
		
		
	}
	
	@Test
	public final void preferencewalltesting3() throws IllegalDimensionException{
		Level<SquareImp> newLevel = new Level<SquareImp>(100, 100, 100, 0);
		
		PlainSquare square = new PlainSquare();
		PlainSquare neigboor = new PlainSquare();
		
		square.setBorder(Directions.North, null);
		neigboor.setBorder(Directions.South, null);
		
		assertEquals(null,newLevel.preferencedWall(square, neigboor, Directions.North, Directions.South));
		
		assertTrue(newLevel.checkValidNeigboorBorders(square, neigboor, Directions.North, Directions.South));
		
		
	}
	
	
	@Test
	public final void addSquareTesting() throws IllegalDimensionException{
		Level<TeleportPlainSquare> newLevel = new Level<TeleportPlainSquare>(100, 100, 100, 5);
		
		ArrayList<SquareImp> list = new ArrayList<SquareImp>();
		PlainSquare square =new PlainSquare();
		TeleportPlainSquare teleport = new TeleportPlainSquare(list);
		teleport.setMaterial(false);
		
		teleport.setTemperature(100, Temperature.CELCIUS);
		
		ArrayList<SquareImp> list2 = new ArrayList<SquareImp>();
		list2.add(square);
		TeleportPlainSquare square2 = new TeleportPlainSquare(list2);
		square2.setTemperature(500, Temperature.CELCIUS);
		square2.setMaterial(false);
		
		newLevel.addSquareToDungeon(10, 10, 5, teleport);
		newLevel.addSquareToDungeon(10, 9, 5, square2);
		
		assertTrue(newLevel.isReachable(teleport, square2));
		
		assertEquals(teleport.getTemperature(), square2.getTemperature(),0);
		assertEquals(300, teleport.getTemperature(),0);
	}
	
	@Test
	public final void setRootTest() throws IllegalDimensionException{
		Level<SquareImp> level = new Level<SquareImp>(100, 100, 100, 5);
		assertTrue(level.getRoot().equals(level));
	}
	
	
	
	
	
	
	
	
	
}
